package me.obstsalat.guildera;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.ArrayList;

import me.obstsalat.guildera.LocationSer;

import org.bukkit.Location;
import org.bukkit.entity.Player;

public class guild {
	
	private String name;
	private int id;
	private Location position;
	private Location teleport;
	private int ep;
	private List<GuildMember> member = new ArrayList<GuildMember>();
	private List<Location2d> area = new ArrayList<Location2d>();
	private guildera instance;
	private long msg_cooldown;
	
	
	guild(guildera plugin, String cName, Location cPosition, String cFounder) { //creating new guild
		name = cName;
		position = cPosition;
		teleport = cPosition;
		ep = 0;
		msg_cooldown = 0;
		do {
			ep = ep + getEpToNextlevel();
		}while(getLevel() <= plugin.config.getInt("startlevel"));
		member.add(new GuildMember(cFounder, 3));
		instance = plugin;
		int m = plugin.config.getInt("guild_size");
		//creating guild area
		for(int cx = -m; cx<=m; cx++) {
			for(int cz = -m; cz<=m; cz++) {
				int nx = position.getBlockX() + cx;
				int nz = position.getBlockZ() + cz;
				area.add(new Location2d(nx, nz));
				
				//creating gravelwall as border
				if(cx == -m || cx == m || cz == -m || cz == m) {
					int y = 1 + worldLib.getSurface(nx, nz, worldLib.SURFACE_HIGHEST, worldLib.SURFACE2_IGNORELIQUID);
					worldLib.spawnBlock(nx, y, nz, 13);
				}
			}
		}
	}
	
	@SuppressWarnings("unchecked")
	guild(String name, guildera plugin) { //loading guilds
		this.name = name;
		instance = plugin;
		msg_cooldown = 0;
		try {
			String path = "";
			String adder = "";
			File file = null;
			for(int t = 1; t<=5; t++) {
				path = plugin.getDataFolder().getCanonicalPath();
				if(t==1) {
					adder = "members";
				} else if(t==2) {
					adder = "area";
				} else if(t==3) {
					adder = "position";
				} else if(t==4){
					adder = "ep";
				} else if(t==5){
					adder = "teleport";
				}
				if(path.contains("\\")) { 
					path = plugin.getDataFolder().getCanonicalPath() + "\\" + this.name + "\\" + adder + ".guild";
				}	else {
					path = plugin.getDataFolder().getCanonicalPath() + "/" + this.name + "/" + adder + ".guild";
				}
				file = new File(path);
				if(file.exists()) {
					FileInputStream fis = new FileInputStream(file);
					ObjectInputStream in = new ObjectInputStream(fis);
					if(t==1) {
						member = (ArrayList<GuildMember>) in.readObject();
					} else if(t==2) {
						area = (ArrayList<Location2d>) in.readObject();
					} else if(t==3) {
						LocationSer cache;
						cache = (LocationSer) in.readObject();
						position = new Location(plugin.overworld,cache.getX(),cache.getY(),cache.getZ());
						teleport = position;
					} else if(t==4){
						ep = (Integer) in.readObject();
					} else if(t==5){
						LocationSer cache;
						cache = (LocationSer) in.readObject();
						teleport = new Location(plugin.overworld,cache.getX(),cache.getY(),cache.getZ());
					}
					fis.close();
				}
			}
		}	catch(Exception ex) {
			plugin.logger.info("ERROR: GuildEra.guild.java:guild() " + ex.toString());
		}
	}
	
	public void save(guildera plugin) {
		String path = "";
		String adder = "";
		File file = null;
		try {
			path = plugin.getDataFolder().getCanonicalPath();
			if(path.contains("\\")) { 
				path = path + "\\" + this.name;
			}	else {
				path = path + "/" + this.name;
			}
			file = new File(path);
			if(!file.exists()) {
				file.mkdirs();
			}
			for(int t = 1; t <= 5; t++) {
				path = plugin.getDataFolder().getCanonicalPath();
				if(t==1) {
					adder = "members";
				} else if(t==2) {
					adder = "area";
				} else if(t==3) {
					adder = "position";
				} else if(t==4){
					adder = "ep";
				} else if(t==5){
					adder = "teleport";
				}
				if(path.contains("\\")) { 
					path = path + "\\" + this.name + "\\" + adder + ".guild";
				}	else {
					path = path + "/" + this.name + "/" + adder + ".guild";
				}
				file = new File(path);
				if(!file.exists()) {
					file.createNewFile();
				}
				if(file.exists()) {
					FileOutputStream fos = new FileOutputStream(file);
					ObjectOutputStream out = new ObjectOutputStream(fos);
					if(t==1) {
						out.writeObject(member);
					} else if(t==2){
						out.writeObject(area);
					} else if(t==3){
						out.writeObject(new LocationSer(position.getBlockX(),position.getBlockY(),position.getBlockZ()));
					} else if(t==4){
						out.writeObject(ep);
					} else if(t==5){
						out.writeObject(new LocationSer(teleport.getBlockX(),teleport.getBlockY(),teleport.getBlockZ()));
					}
					fos.close();
				}
			}
		} catch(Exception ex) {
			plugin.logger.info("ERROR: GuildEra.guild.java:save() " + ex.toString());
		}
	}
	
	public int getLevel() {
		boolean last = true;
		int x = 0;
		do {
			x++;
			if( levelAlgorithm(x) > ep && last) {
				last = false;
			}
			
		} while (last);
		return x-1;
	}

	public boolean isInGuild(Location l) {
		if(l.getWorld() == instance.overworld) {
			boolean c = false;
			for(Location2d ld : area) {
				if(ld.equal(new Location2d(l))) {
					c = true;
				}
			}
			return c;
		} else {
			return false;
		}
	}
	
	public boolean isInGuild(Location2d l) {
		boolean c = false;
		for(Location2d ld : area) {
			if(ld.equal(l)) {
				c = true;
			}
		}
		return c;
	}
	
	public int getId() {
		return id;
	}
	
	public String getName() {
		return name;
	}
	
	public Location getPosition() {
		return position;
	}
	
	public boolean hasMember(String str) {
		if(getMember(str) != null) {
			return true;
		} else {
			return false;
		}
	}
	
	public void addMember(String str) {
		member.add(new GuildMember(str, 1));
	}
	
	public GuildMember getMember(String str) {
		GuildMember r = null;
		for(GuildMember gm : member) {
			if(gm.getName().equals(str)) {
				r = gm;
			}
		}
		return r;
	}
	
	public void removeMember(String str) {
		for(int i = 0; i < member.size(); i++) {
			if(member.get(i).getName().equals(str)) {
				member.remove(i);
			}
		}
	}
	
	public void setRank(GuildMember gm, int rank) {
		for(GuildMember g : member) {
			if(g.getName().equals(gm.getName())) {
				g.setRank(rank);
				this.save(instance);
			}
		}
	}
	
	public int getNumMember() {
		return member.size();
	}
	
	public List<GuildMember> getMembers() {
		return member;
	}
	
	public int getEpToNextlevel() {
		int x = getLevel() + 1;
		return (int) (levelAlgorithm(x) - ep);
	}
	
	public void addEp(int amount) {
		int old_lvl = this.getLevel();
		this.ep += amount;
		int new_lvl = this.getLevel();
		if(old_lvl!=new_lvl) {
			for(Player p : instance.getServer().getOnlinePlayers()) {
				p.sendMessage(name + " raised his level to " + new_lvl + ".");
			}
		}
	}
	
	private int levelAlgorithm(int x) {
		int result = 0;
		for(int i = 0; i <= x; i++) {
			result += 5*i*Math.pow(3, i/10);
		}
		return result;
	}
	
	public void announce(String str) {
		for(GuildMember gm : member) {
			Player ply = instance.getServer().getPlayer(gm.getName());
			if(ply != null && ply instanceof Player) {
				ply.sendMessage(str);
			}
		}
	}
	
	public void setMsgCooldown(long cd) {
		msg_cooldown = cd;
	}
	
	public long getMsgCooldown() {
		return msg_cooldown;
	}

	public long getArea() {
		long c = 0;
		for(@SuppressWarnings("unused") Location2d l : area) {
			c++;
		}
		return c;
	}
	
	public Location getTeleport() {
		return teleport;
	}
	
	public void setTeleport(Location tele) {
		teleport = tele;
	}
	
	public List<Location2d> getAreaList() {
		return area;
	}
	
	public void addArea(Location2d l2d) {
		boolean has = false;
		for(int i = 0; i < area.size(); i++) {
			if(area.get(i).equal(l2d)) {
				has = true;
			}
		}
		if(!has) {
			area.add(l2d);
		}
	}
	
	public void removeArea(Location2d l2d) {
		for(int i = 0; i < area.size(); i++) {
			if(area.get(i).equal(l2d)) {
				area.remove(i);
			}
		}
	}
}
